import datetime
import string
import threading

class ChargingPileState(object):
    def __init__(self, pile_id: int, functioning: int, charging_times: int, charging_duration: int, charging_quantity: float):
        self.__charging_pile_id = pile_id
        self.__proper_functioning = functioning
        self.__cumulative_charging_times = charging_times
        self.__cumulative_charging_duration = charging_duration
        self.__accumulative_charging_quantity = charging_quantity

    def change_functioning(self, new_functioning: int):
        self.__proper_functioning = new_functioning

    def change_charging_info(self, new_charging_times: int, new_charging_duration: int, new_charging_quantity: float):
        self.__cumulative_charging_times = new_charging_times
        self.__cumulative_charging_duration = new_charging_duration
        self.__accumulative_charging_quantity = new_charging_quantity

    def get_charging_pile_id(self):
        return self.__charging_pile_id

    def get_proper_functioning(self):
        return self.__proper_functioning

    def get_cumulative_charging_times(self):
        return self.__cumulative_charging_times

    def get_cumulative_charging_duration(self):
        return self.__cumulative_charging_duration

    def get_accumulative_charging_quantity(self):
        return self.__accumulative_charging_quantity


class AllCarInformation(object):
    def __init__(self, user_id: int, total_battery_capacity: float, request_charging_quantity: float, start_queue_time: datetime.datetime, pattern: string, state: int, line_number: int, pile: int):
        self.__user_id = user_id
        self.__total_battery_capacity = total_battery_capacity
        self.__request_charging_quantity = request_charging_quantity
        self.__start_queue_time = start_queue_time
        self.__pattern = pattern
        self.__state = state
        self.__line_number = line_number
        self.__pile = pile

    def change_state(self, new_state: int):
        self.__state = new_state

    def change_pile(self, new_pile: int):
        self.__pile = new_pile

    def change_request_charging_quantity(self, new_request_charging_quantity: float):
        self.__request_charging_quantity = new_request_charging_quantity

    def change_pattern(self, new_pattern: string):
        self.__pattern = new_pattern

    def change_line_number(self, new_line_number: int):
        self.__line_number = new_line_number

    def get_user_id(self):
        return self.__user_id

    def get_total_battery_capacity(self):
        return self.__total_battery_capacity

    def get_request_charging_quantity(self):
        return self.__request_charging_quantity

    def get_start_queue_time(self):
        return self.__start_queue_time

    def get_pattern(self):
        return self.__pattern

    def get_state(self):
        return self.__state

    def get_line_number(self):
        return self.__line_number

    def get_pile(self):
        return self.__pile


# sl1 = ChargingPileState(1, 0, 10, 20, 30)
# sl2 = ChargingPileState(2, 0, 1, 2, 3)
# sl3 = ChargingPileState(3, 1, 30, 20, 10)

# al1 = AllCarInformation(1,55.5,66.6,datetime.datetime.now(),0,1)
# print(al1.get_start_queue_time())


# dic = [sl1, sl2, sl3]
# print(dic[0].accumulative_charging_quantity)
# sl1.accumulative_charging_quantity = 1000
# print(dic[0].accumulative_charging_quantity)

class CancellableTimer(threading.Thread):

    def start_OL(self):
        self.start()
        self.start_time = datetime.datetime.now()

    def get_start_time(self):
        return self.start_time
    
    def __init__(self, interval, function, **kwargs):
        """ just do like threading.Timer does """
        threading.Thread.__init__(self)
        self.interval = interval
        self.function = function
        self.kwargs = kwargs
        self.finished = threading.Event()

    def cancel(self):
        """ atomic cancel this timer, 
            if True, it means successfully cancelled,
            if False, it means it's already executing or stopped already
        """
        return self.test_and_set()

            

    def test_and_set(self):
        """ return value will be the False if successfully set """
        with self.finished._cond:
            if not self.finished._flag:
                self.finished._flag = True
                self.finished._cond.notify_all()
                return True
            else:
                return False

    def run(self):
        self.finished.wait(self.interval)
        if self.test_and_set():
            """ if event is not set """
            self.function(**self.kwargs)
